package com.warningrc.image;

import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.awt.image.WritableRaster;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * {@code java.awt.Image}工具类
 * 
 * @author <a href="http://weibo.com/weibowarning">王宁</a><br/> email: <a
 *         href="mailto:childe.wangning@gmail.com">childe.wangning@gmail.com</a>
 * @date 2012-3-12
 */
public class ImageTools { 
	private static int convertPixel(int x, int y, int w, int h, int pixel,
			int fadeSpeed) {
		int alpha = (pixel >> 24) & 0xff;
		int red = (pixel >> 16) & 0xff;
		int green = (pixel >> 8) & 0xff;
		int blue = (pixel) & 0xff;
		double percent = (double) (y * 100) / h / 100d;
		for (int i = 0; i < fadeSpeed; i++) {
			percent = percent * percent;
		}
		alpha = (int) (alpha * percent);
		alpha = Math.min(alpha, 150);
		int gray = (red + green + blue) / 3;
		return ((alpha << 24) + (gray << 16) + (gray << 8) + gray);
	}

	/**
	 * 对原图像做处理，返回一个倒影的图像
	 * 
	 * @param image
	 *            原图像
	 * @param fadeSpeed
	 *            倒影消失速率
	 * @return 原图像的倒影图像
	 */
	public static Image createShadowImage(Image image, int fadeSpeed) {
		int w = image.getWidth(null);
		int h = image.getHeight(null);
		int[] pixels = new int[w * h];
		PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
		try {
			pg.grabPixels();
		} catch (Exception e) {
			return null;
		}
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				pixels[j * w + i] = convertPixel(i, j, w, h, pixels[j * w + i],
						fadeSpeed);
			}
		}
		int[] newPixels = new int[w * h];
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				newPixels[j * w + i] = pixels[(h - j - 1) * w + i];
			}
		}
		MemoryImageSource source = new MemoryImageSource(w, h, newPixels, 0, w);
		return Toolkit.getDefaultToolkit().createImage(source);
	}

	public static void createThumbnail(String filename, int thumbWidth, int thumbHeight,
			int quality, String outFilename) throws InterruptedException,
			FileNotFoundException, IOException {
		// load image from filename
		Image image = Toolkit.getDefaultToolkit().getImage(filename);
		MediaTracker mediaTracker = new MediaTracker(new Container());
		mediaTracker.addImage(image, 0);
		mediaTracker.waitForID(0);
		// use this to test for errors at this point:
		// System.out.println(mediaTracker.isErrorAny());
		// determine thumbnail size from WIDTH and HEIGHT
		double thumbRatio = (double) thumbWidth / (double) thumbHeight;
		int imageWidth = image.getWidth(null);
		int imageHeight = image.getHeight(null);
		double imageRatio = (double) imageWidth / (double) imageHeight;
		if (thumbRatio < imageRatio) {
			thumbHeight = (int) (thumbWidth / imageRatio);
		} else {
			thumbWidth = (int) (thumbHeight * imageRatio);
		}
		// draw original image to thumbnail image object and
		// scale it to the new size on-the-fly
		BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D graphics2D = thumbImage.createGraphics();
		graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
		// save thumbnail image to outFilename
		BufferedOutputStream out = new BufferedOutputStream(
				new FileOutputStream(outFilename));
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(thumbImage);
		quality = Math.max(0, Math.min(quality, 100));
		param.setQuality((float) quality / 100.0f, false);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(thumbImage);
		out.close();
	}

	public static BufferedImage resize(BufferedImage source, int targetW,
			int targetH) {
		// targetW，targetH分别表示目标长和宽
		int type = source.getType();
		BufferedImage target = null;
		double sx = (double) targetW / source.getWidth();
		double sy = (double) targetH / source.getHeight();
		// 这里想实现在targetW，targetH范围内实现等比缩放。如果不需要等比缩放
		// 则将下面的if else语句注释即可
		if (sx > sy) {
			sx = sy;
			targetW = (int) (sx * source.getWidth());
		} else {
			sy = sx;
			targetH = (int) (sy * source.getHeight());
		}
		if (type == BufferedImage.TYPE_CUSTOM) { // handmade
			ColorModel cm = source.getColorModel();
			WritableRaster raster = cm.createCompatibleWritableRaster(targetW,
					targetH);
			boolean alphaPremultiplied = cm.isAlphaPremultiplied();
			target = new BufferedImage(cm, raster, alphaPremultiplied, null);
		} else
			target = new BufferedImage(targetW, targetH, type);
		Graphics2D g = target.createGraphics();
		// smoother than exlax:
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
		g.dispose();
		return target;
	}

	public static void saveImageAsJpg(String fromFileStr, String saveToFileStr,
			int width, int hight) throws Exception {
		BufferedImage srcImage;
		String imgType = "JPEG";
		if (fromFileStr.toLowerCase().endsWith(".png")) {
			imgType = "PNG";
		}
		File saveFile = new File(saveToFileStr);
		File fromFile = new File(fromFileStr);
		srcImage = ImageIO.read(fromFile);
		if (width > 0 || hight > 0) {
			srcImage = resize(srcImage, width, hight);
		}
		ImageIO.write(srcImage, imgType, saveFile);
	}

	public static void main(String artgs[]) throws Exception {
		long start=System.currentTimeMillis();
//		saveImageAsJpg("d:/a.JPG","d:/b.JPEG",1024,768);
		createThumbnail("d:/a.JPG",200,200,100,"d:/c.JPEG");
		System.out.println(System.currentTimeMillis()-start);
	}
}
